package tech.waterism.topo.context;

import lombok.Data;
import tech.waterism.topo.model.*;

import java.util.*;

/**
 * 计算上下文
 * 
 * <p>统一管理调洪演算过程中的所有状态和缓存数据，避免在方法之间传递大量参数。
 * 
 * <h3>核心职责：</h3>
 * <ul>
 *   <li>管理拓扑节点数据</li>
 *   <li>管理计算结果缓存（单站缓存、联调缓存）</li>
 *   <li>管理联调信息</li>
 *   <li>管理时间参数</li>
 * </ul>
 * 
 * @author waterism
 * @since 1.0.0
 */
@Data
public class CalculationContext {
    
    // ========== 时间参数 ==========
    /** 预报起始时间（起调时间） */
    private Date startTime;
    
    /** 实测起始时间 */
    private Date observationStartTime;
    
    /** 修改时间（用于指定泄流方式的起始时间） */
    private Date modifyTime;
    
    // ========== 拓扑信息 ==========
    /** 拓扑节点列表 */
    private List<TopoNode> nodes;
    
    /** 节点索引映射：站码 -> 节点索引位置 */
    private Map<String, Integer> nodeIndexMap;
    
    // ========== 联调信息 ==========
    /** 联调组列表 */
    private List<JointDispatchGroup> jointGroups;
    
    /** 联调组映射：联调组ID -> 上游起点站码列表 */
    private Map<Integer, List<String>> jointTriggerMap;
    
    /** 联调组详情：联调组ID -> 联调对象 */
    private Map<Integer, JointDispatchGroup> jointGroupMap;
    
    /** 当前触发的联调组 */
    private JointDispatchGroup triggeredGroup;
    
    // ========== 缓存管理 ==========
    /** 
     * 单站计算结果缓存：站码 -> 节点结果
     * <p>用于避免重复计算同一个站点，下游节点可以直接复用上游的计算结果
     */
    private Map<String, NodeResult> resultCache;
    
    /** 
     * 联调计算结果缓存：站码 -> 节点结果
     * <p>联调计算使用独立的缓存空间，避免与单站计算混淆
     */
    private Map<String, NodeResult> jointResultCache;
    
    /** 
     * 枢纽分流数据缓存：分流口站码 -> 流量时序数据
     * <p>记录枢纽各分流口的流量过程，供下游使用
     */
    private Map<String, List<TimeSeriesData>> hubDistributionCache;
    
    // ========== 全局配置 ==========
    /** 调度类型 */
    private Integer dispatchType;
    
    /** 出流类型 */
    private Integer outFlowType;
    
    /** 是否使用水文模型 */
    private Boolean useHydro;
    
    /**
     * 默认构造函数
     */
    public CalculationContext() {
        this.resultCache = new HashMap<>();
        this.jointResultCache = new HashMap<>();
        this.hubDistributionCache = new HashMap<>();
        this.nodeIndexMap = new HashMap<>();
        this.jointTriggerMap = new HashMap<>();
        this.jointGroupMap = new HashMap<>();
        this.jointGroups = new ArrayList<>();
    }
    
    // ========== 缓存操作方法 ==========
    
    /**
     * 检查节点是否已计算（在单站缓存中）
     * 
     * @param stcd 站码
     * @return true表示已缓存
     */
    public boolean isCached(String stcd) {
        return resultCache.containsKey(stcd);
    }
    
    /**
     * 获取缓存的节点结果
     * 
     * @param stcd 站码
     * @return 节点结果，不存在则返回null
     */
    public NodeResult getCachedResult(String stcd) {
        return resultCache.get(stcd);
    }
    
    /**
     * 缓存节点计算结果
     * 
     * @param stcd 站码
     * @param result 节点结果
     */
    public void cacheResult(String stcd, NodeResult result) {
        resultCache.put(stcd, result);
    }
    
    /**
     * 缓存联调节点计算结果
     * 
     * @param stcd 站码
     * @param result 节点结果
     */
    public void cacheJointResult(String stcd, NodeResult result) {
        jointResultCache.put(stcd, result);
    }
    
    /**
     * 将联调缓存合并到主缓存
     * <p>联调计算完成后，需要将联调结果同步到主缓存中，供后续节点使用
     */
    public void mergeJointResults() {
        resultCache.putAll(jointResultCache);
        // 清空联调缓存，准备下一次联调
        jointResultCache.clear();
    }
    
    /**
     * 获取节点索引位置
     * 
     * @param stcd 站码
     * @return 索引位置，不存在则返回null
     */
    public Integer getNodeIndex(String stcd) {
        return nodeIndexMap.get(stcd);
    }
    
    /**
     * 添加枢纽分流数据
     * 
     * @param distributionStcd 分流口站码
     * @param data 流量时序数据
     */
    public void addHubDistribution(String distributionStcd, List<TimeSeriesData> data) {
        hubDistributionCache.put(distributionStcd, data);
    }
    
    /**
     * 获取枢纽分流数据
     * 
     * @param distributionStcd 分流口站码
     * @return 流量时序数据，不存在则返回null
     */
    public List<TimeSeriesData> getHubDistribution(String distributionStcd) {
        return hubDistributionCache.get(distributionStcd);
    }
    
    /**
     * 检查枢纽分流数据是否存在
     * 
     * @param distributionStcd 分流口站码
     * @return true表示存在
     */
    public boolean hasHubDistribution(String distributionStcd) {
        return hubDistributionCache.containsKey(distributionStcd);
    }
    
    /**
     * 设置当前触发的联调组
     * 
     * @param groupId 联调组ID
     */
    public void setTriggeredGroup(Integer groupId) {
        this.triggeredGroup = jointGroupMap.get(groupId);
    }
    
    /**
     * 检查联调是否已触发
     * 
     * @return true表示当前有联调组被触发
     */
    public boolean hasTriggeredGroup() {
        return triggeredGroup != null;
    }
    
    /**
     * 清除触发的联调组
     */
    public void clearTriggeredGroup() {
        this.triggeredGroup = null;
    }
}

